//
//  WBStatusListViewModel.swift
//  SwiftWeibo
//
//  Created by Lausen on 2017/4/16.
//  Copyright © 2017年 id. All rights reserved.
//

import Foundation
import YYModel
import SDWebImage

/// 微博的视图模型
/*
 父类的选择:
 -- 如果类需要使用 "KVC" 或者字典转模型框架设置对象值,类就需要继承自NSObject
 -- 如果类只是包装一些逻辑代码(写了一些函数),可以不用任何父类,好处:更加轻量级
 -- 提示:如果用OC写,一律都继承自NSObject
 
 使命:
 1:字典转模型
 2:下拉/ 上拉 刷新数据处理
 */

private let pullUpMaxTimes = 3

class WBStatusListViewModel {
    
    lazy var statusList = [WBStatusViewModel]()
    
    var pullUpErrorTimes = 0
    
    /// 加载网络请求的微博数据
    ///
    /// - Parameters:
    ///   - since_id: 若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
    ///   - max_id: 若指定此参数，则返回ID小于或等于max_id的微博，默认为0
    ///   - completion: 加载完成的回调.主要用来判断是否请求成功了
    func loadStatus(pullUp: Bool = false,completion:@escaping(_ isSuccess: Bool,_ hasMorePullUp: Bool) -> ()) {
        
        if pullUp && (pullUpErrorTimes > pullUpMaxTimes) {
            
            completion(true, false)
            
            return
        }
        
        let since_id = pullUp ? 0 : statusList.first?.status.id ?? 0
        let max_id = !pullUp ? 0 : statusList.last?.status.id ?? 0
        
        WBNetworkManager.shared.statusList(since_id: since_id, max_id: max_id) { (json, isSuccess) in
            
            if !isSuccess{ //如果失败了,直接返回失败,并且不刷新
            
                completion(false, false)
                
                return
            }
            
            var array = [WBStatusViewModel]()
            
            for dict in json ?? []{
                
                guard let model = WBStatus.yy_model(with: dict) else{
                    //在for循环里面,不能直接返回,需要继续执行
                    continue
                }
                
                array.append(WBStatusViewModel.init(model: model))
            }
            
            
            
            print("两层模型\(array)")
            
            if pullUp {
                
                //如果是上拉刷新.就把返回来的数据加入到数据的后面去
                self.statusList += array
                
            }else{
                
                //如果不是上拉的,就把返回来的数据加入到数据的前面去
                self.statusList = array + self.statusList
            }
            
            if pullUp  && array.count == 0{
                
                self.pullUpErrorTimes += 1
                
                completion(isSuccess, false)
                
            }else{
                
                self.cacheSingleImage(list: array,finish:completion)
                
//                completion(isSuccess,true)
            }
        }
    }
    
    /// 缓存单张图片的方法                                       闭包当做参数来传递
    private func cacheSingleImage(list: [WBStatusViewModel],finish:@escaping(_ isSuccess: Bool,_ hasMorePullUp: Bool) -> ()){
    
        let group = DispatchGroup()
        
        
        ///记录图像的长度
        var lenght = 0
        
        ///1:判断图像的数量
        for vm in list{
            
            if vm.picURLS?.count != 1 {
                continue
            }
            
            ///2:代码执行到这儿,数组中有且只有一张图像
            guard let pic = vm.picURLS![0].thumbnail_pic,
                let url = URL(string: pic) else {
                    
                    continue
            }
            
            group.enter()
            
            //1)downloadImage是 SDWebImage 的核心方法,经常用到的sd_setImageXX.最后都会调用这个方法
            //2)图像下载完成之后,会自动保存在沙盒中,文件路径是url的md5
            //3)如果沙盒中已经存在缓存的图像,后续使用SD通过URL加载图像,都会加载本地沙盒图像
            //4)不会发起网络请求了,同样,回调方法一样会回调
            _ = SDWebImageManager.shared().imageDownloader?.downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _) in
                
                if let image = image,
                    let data = UIImagePNGRepresentation(image){
                    
                    lenght += data.count
                    
                    ///确定完成图像的缓存之后,再去调用单张图像的设置尺寸的方法
                    vm.updataSingleImageSize(image: image)
                }
                
                group.leave()
            })
        }
        
        group.notify(queue: DispatchQueue.main, execute: {
            
            finish(true, true)
        })
    }
}
